#include <GamePanel.h>

GamePanel::GamePanel()
{  
    fundoJogoImg = new QPixmap();
    pecaJog1 = new QPixmap();
    pecaJog2 = new QPixmap();
    pecaTran = new QPixmap();
    pecaDica = new QPixmap();
    fundoJogo = new QLabel(this);

    fundoJogoImg->load(":/fundo_jogo.png");
    pecaJog1->load(":/pcB.png");
    pecaJog2->load(":/pcP.png");
    pecaTran->load(":/pcT.png");
    pecaDica->load(":/pcH.png");

    for(int i = 0; i < TAM; i++)
        for(int j = 0;j < TAM; j++)
        {
            pecas[i][j] = new QLabel(this);
            pecas[i][j]->move(primeiroQuadradoX+tamanhoQuadrado*j, primeiroQuadradoY+tamanhoQuadrado*i);
            pecas[i][j]->setPixmap(*pecaTran);
            pecas[i][j]->raise();
            pecas[i][j]->show();
        }

    p1 = new Jogador(tr("Human Player").toStdString(), 1);
    p2 = new Jogador(tr("AI Player").toStdString(), 2);

    tJogo = NULL;

    trspeed = TRSPEED_MED;
    opIA = new MinMax();
    opIA->setProfundidade(DIFFICULT_MEDIUM); //1 == testes mais rapidos :P
   
    fundoJogo->setPixmap(*fundoJogoImg);
    fundoJogo->show();

    //iniciaNovoJogo();
}

void GamePanel::mouseReleaseEvent(QMouseEvent *event)
{
    int pI, pJ;
    bool bDicas = false;
    Coordenada c;
    QMessageBox msgBox(this);
    QTime timer;

    msgBox.setWindowTitle(tr("I have something very important to say..."));
    msgBox.setIcon(QMessageBox::Information);
    msgBox.setFixedSize(200, 200);

    if(!jogoNaoAcabou())return;

    pI = getQuadradoI(event->y());
    pJ = getQuadradoJ(event->x());

    c.setX(pI);
    c.setY(pJ);

    if(pI != -1 && pJ != -1 && jogPossiveis[pI][pJ] == true)
    {
	    humanoJoga(c);
		
	    geraJogadasPossiveis(p2);
	    if(semJogadas == false)
	    {
            if(mostraTodasDicas)
            {
                alteraMostraTodasJogadas();
                bDicas = true;
            }
            else updatePanel();

            emit changeTurn(p2);
            emit updateStatusBar(tr("AI is thinking..."));
            repaint();

            iaJoga();

            geraJogadasPossiveis(p1);
            while(semJogadas == true)
            {
                geraJogadasPossiveis(p2);
                if(semJogadas == true) //Nem o jogador humano, nem a IA podem mais jogar.
                {
                    msgBox.setText(tr("Oops! It looks like that no one can make anymore plays. So, the game has ended!"));	
                    msgBox.exec();
                    if(casasOcupadas != 64)jogoAcabou = true;
                    jogoNaoAcabou();
                    return;
                }

				msgBox.setText(tr("You don't have any possible moves, AI is going to play again."));
				msgBox.exec();
				iaJoga();
				geraJogadasPossiveis(p1);					
            }
            
            emit changeTurn(p1);
            emit updateStatusBar(tr("It's your turn now!"));

            if(bDicas)alteraMostraTodasJogadas();
            else updatePanel();
        }
        else if(jogoNaoAcabou())
        {
            geraJogadasPossiveis(p1);

            if(semJogadas == true) //Nem o jogador humano, nem a IA podem mais jogar.
            {
                msgBox.setText(tr("Oops! It looks like that no one can make anymore plays. So, the game has ended!"));  
                msgBox.exec();
                if(casasOcupadas != 64)jogoAcabou = true;
				jogoNaoAcabou();
				return;
            }

			msgBox.setText(tr("Hey! You made a really good move, AI doesn't have any possible moves to play. Play again =]"));
			msgBox.exec();			
        }

    }
}

void GamePanel::iniciaNovoJogo()
{
    delete tJogo;
    tJogo = new Tabuleiro(*p1, *p2);

    //Tabuleiro inicial de verdade:
    tJogo->setPos(3,3, p1->getId());
    tJogo->setPos(3,4, p2->getId());
    tJogo->setPos(4,3, p2->getId());
    tJogo->setPos(4,4, p1->getId());

    //Tabuleiro inicial de teste nro 289347329482094:
    /*tJogo->setPos(0,1, p2->getId());
    tJogo->setPos(0,2, p1->getId());
    tJogo->setPos(1,0, p2->getId());
    tJogo->setPos(2,0, p2->getId());
    tJogo->setPos(3,1, p1->getId());
    tJogo->setPos(3,0, p2->getId());
    tJogo->setPos(4,0, p2->getId());
    tJogo->setPos(5,0, p2->getId());
    tJogo->setPos(6,0, p2->getId());
    tJogo->setPos(7,0, p2->getId());
    tJogo->setPos(7,1, p1->getId());*/

    casasOcupadas = 4;
    jogoAcabou = false;

    mostraTodasDicas = false;

    calculaScore();

    emit changeTurn(p1);
    emit updateStatusBar(tr("Make the first play!"));

    updatePanel();
    geraJogadasPossiveis(p1);
}

void GamePanel::updatePanel()
{
    for(int i = 0; i < TAM; i++)
        for(int j = 0; j < TAM; j++)
            updatePeca(i, j);

    repaint();
}

void GamePanel::updatePeca(int i, int j)
{
    if(i < 0 || i > 7 || j < 0 || j > 7) return;


    if(tJogo->getPos(i,j) == p1->getId())
    {
        pecas[i][j]->setPixmap(*pecaJog1);
    }
    else if(tJogo->getPos(i,j) == p2->getId())
    {
        pecas[i][j]->setPixmap(*pecaJog2);
    }
    else if(mostraTodasDicas && jogPossiveis[i][j])
    {
        pecas[i][j]->setPixmap(*pecaDica);
    }
    else
    {
        pecas[i][j]->setPixmap(*pecaTran);
    }

    pecas[i][j]->repaint();
}

int GamePanel::getQuadradoI(int y)
{
    if(y < primeiroQuadradoY || y > (primeiroQuadradoY + TAM*tamanhoQuadrado)) return -1;
    else return (y-primeiroQuadradoY)/tamanhoQuadrado;
}

int GamePanel::getQuadradoJ(int x)
{
    if(x < primeiroQuadradoX || x > (primeiroQuadradoX + TAM*tamanhoQuadrado)) return -1;
    else return (x-primeiroQuadradoX)/tamanhoQuadrado;
}

void GamePanel::geraJogadasPossiveis(Jogador* jg)
{
	for(int i = 0;i < TAM;i++)
		for(int j = 0;j < TAM; j++)
			jogPossiveis[i][j] = false;

	semJogadas = true;

	set<Coordenada> jp = tJogo->jogadasPossiveis(*jg);
	qDebug() << "QTD: [" << jp.size() << "]\n";
	set<Coordenada>::iterator it;

	for(it = jp.begin(); it != jp.end(); ++it)
	{
		jogPossiveis[it->getX()][it->getY()] = true;
		semJogadas = false;
	}
}

void GamePanel::alteraMostraTodasJogadas()
{
    if(mostraTodasDicas == false)
        mostraTodasDicas = true;
    else
        mostraTodasDicas = false;       

    updatePanel();
}

void GamePanel::humanoJoga(Coordenada c)
{
    tJogo->joga(c, *p1);
    casasOcupadas++;
    calculaScore();
    updatePanel();
}

void GamePanel::iaJoga()
{
    QTime timer;
    opIA->zera();
	
    Jogada j = opIA->executa(*tJogo, *p2, *p1);
    qDebug() << "Nro de nos gerados: " << opIA->NNOS;
	
    for(int i = 0; i < trspeed; i++)
    {
        if(i%2 == 0)
        {
            tJogo->setPos(j.getCoordenada().getX(), j.getCoordenada().getY(), p2->getId());
            updatePeca(j.getCoordenada().getX(), j.getCoordenada().getY());
            repaint();
            
            timer.start();
            while(timer.elapsed() < 200) ;
        }
        else
        {
            tJogo->setPos(j.getCoordenada().getX(), j.getCoordenada().getY(), 0);
            updatePeca(j.getCoordenada().getX(), j.getCoordenada().getY());
            repaint();
            
            timer.start();
            while(timer.elapsed() < 200) ;
        }
    }

    //tJogo->setPos(j.getCoordenada().getX(), j.getCoordenada().getY(), 0);
    tJogo->joga(j.getCoordenada(), *p2);
    casasOcupadas++;
    calculaScore();
    updatePanel();
}

bool GamePanel::jogoNaoAcabou()
{
    if(casasOcupadas < 64 && jogoAcabou == false)return true;
    else if(casasOcupadas == 64 && jogoAcabou == true) return false;
    else
    {
        casasOcupadas = 64;
        jogoAcabou = true;
        calculaScore();
        QMessageBox msgBox(this);
        msgBox.setWindowTitle(tr("I have something very important to say..."));
		if(scorePlayer1 == scorePlayer2)
			msgBox.setText(tr("The game has ended. Final score is: ") + QString::number(scorePlayer1) + " x " +
				QString::number(scorePlayer2) + "\nThe game ended in a draw." );
		else if(scorePlayer1 > scorePlayer2)
			msgBox.setText(tr("The game has ended. Final score is: ") + QString::number(scorePlayer1) + " x " +
				QString::number(scorePlayer2) + "\nYou win!               " );		
		else
			msgBox.setText(tr("The game has ended. Final score is: ") + QString::number(scorePlayer1) + " x " +
				QString::number(scorePlayer2) + "\nOh no, you lost =/ It may be bad luck, you should try again!" );		

		updateStatusBar(tr("The game has ended!"));
				
        msgBox.setFixedSize(400, 400);
        msgBox.exec();
        return false;
    }

}

void GamePanel::calculaScore()
{
    scorePlayer1 = 0;
    scorePlayer2 = 0;

    for(int i = 0; i < TAM; i++)
    {
        for(int j = 0; j < TAM; j++)
        {
            if(tJogo->getPos(i,j) == p1->getId())scorePlayer1++;
            else if(tJogo->getPos(i,j) == p2->getId())scorePlayer2++;
        }
    }

    emit updateScore(scorePlayer1, scorePlayer2);
}

void GamePanel::updateEvalFunc(FuncaoAvaliacao* fnc)
{
    opIA->setFuncaoAvaliacao(fnc);
}

void GamePanel::updateAILevel(int level)
{
    opIA->setProfundidade(level);
}

void GamePanel::updateTRSpeed(int speed)
{
    trspeed = speed;
}
